/**
 * Copyright (C) <2023> <Boundivore> <boundivore@foxmail.com>
 * <p>
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Apache License, Version 2.0
 * as published by the Apache Software Foundation.
 * <p>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Apache License, Version 2.0 for more details.
 * <p>
 * You should have received a copy of the Apache License, Version 2.0
 * along with this program; if not, you can obtain a copy at
 * http://www.apache.org/licenses/LICENSE-2.0.
 */
/**
 * CheckLogModal - 查看日志弹窗
 * @param {boolean} isModalOpen - 弹窗是否打开
 * @param {function} handleCancel - 弹窗取消的回调函数
 * @author Tracy
 */
import { FC, useEffect, useState, memo, useMemo, useRef } from 'react';
import { Button, Tabs, Modal, Flex, Card, Row, Col, Popover } from 'antd';
import type { TabsProps } from 'antd';
import CodeMirror from '@uiw/react-codemirror';
import { StreamLanguage } from '@codemirror/language';
import { shell } from '@codemirror/legacy-modes/mode/shell';
import { yaml } from '@codemirror/legacy-modes/mode/yaml';
import { useSearchParams } from 'react-router-dom';
import { t } from 'i18next';
import APIConfig from '@/api/config';
import RequestHttp from '@/api';
import useStore from '@/store/store';
import useCurrentCluster from '@/hooks/useCurrentCluster';
import { useCodeEditorTheme } from '@/hooks/useCodeEditorTheme';
import ThemeToggle from '@/components/themeToggle';
import FullScreenButton from './fullScreenButton';
import { JobLogVo, NodeJobLogVo, UnifiedLogData } from '@/api/interface';

interface CheckLogModalProps {
	isModalOpen: boolean;
	nodeId: string;
	handleCancel: () => void;
	type?: string;
}

const unifyLogData = (data: JobLogVo | NodeJobLogVo, type: 'jobProgress' | 'nodeJobProgress'): UnifiedLogData => {
	if (type === 'jobProgress') {
		const jobData = data as JobLogVo;
		return {
			logErrOut: jobData.LogErrOut,
			logStdOut: jobData.LogStdOut,
			nodeId: jobData.NodeId,
			nodeHostname: jobData.NodeHostname,
			jobId: jobData.JobId,
			jobName: jobData.JobName,
			stepId: jobData.StepId,
			stepName: jobData.StepName,
			taskId: jobData.TaskId,
			taskName: jobData.TaskName,
			stageId: jobData.StageId,
			stageName: jobData.StageName
		};
	} else {
		const nodeData = data as NodeJobLogVo;
		return {
			logErrOut: nodeData.LogErrOut,
			logStdOut: nodeData.LogStdOut,
			nodeId: nodeData.NodeId,
			nodeHostname: nodeData.NodeHostname,
			jobId: nodeData.NodeJobId,
			jobName: nodeData.NodeJobName,
			stepId: nodeData.StepId,
			stepName: nodeData.NodeStepName,
			taskId: nodeData.NodeTaskId,
			taskName: nodeData.NodeTaskName
		};
	}
};

const CheckLogModal: FC<CheckLogModalProps> = memo(({ isModalOpen, nodeId, handleCancel, type = 'nodeJobProgress' }) => {
	const [searchParams] = useSearchParams();
	const id = searchParams.get('id');
	const { jobNodeId, jobId } = useStore();
	const { selectCluster } = useCurrentCluster();
	const { createDarkTheme } = useCodeEditorTheme();
	const [logData, setLogData] = useState<UnifiedLogData[]>([]);
	const [tabsData, setTabsData] = useState<TabsProps['items']>([]);
	const [activeTab, setActiveTab] = useState('');

	const [isDarkMode, setIsDarkMode] = useState(() => {
		return localStorage.getItem('theme') === 'dark';
	});
	const containerRef = useRef<HTMLDivElement>(null);
	const containerRef2 = useRef<HTMLDivElement>(null);
	const [isFullScreen, setIsFullScreen] = useState(false);

	// 保存主题选择
	useEffect(() => {
		localStorage.setItem('theme', isDarkMode ? 'dark' : 'light');
	}, [isDarkMode]);

	const tabItems = useMemo(
		() => [
			{
				key: '1',
				label: '错误输出',
				children: (
					<div
						ref={containerRef}
						className={`relative w-full pt-4 ${isFullScreen && 'fixed inset-0 z-50'} ${
							isDarkMode ? 'bg-[#1e1e1e]' : 'bg-white'
						} `}
					>
						<Flex justify="flex-end">
							<FullScreenButton containerRef={containerRef} isFullScreen={isFullScreen} setIsFullScreen={setIsFullScreen} />
						</Flex>
						<CodeMirror
							className={`${isFullScreen ? 'h-[100%]' : 'h-[488px]'} overflow-auto`}
							value={logData.find(log => log.stepId === activeTab)?.logErrOut || ''}
							extensions={[StreamLanguage.define(shell), StreamLanguage.define(yaml), ...(isDarkMode ? createDarkTheme() : [])]}
							editable={false}
						/>
					</div>
				)
			},
			{
				key: '2',
				label: '标准输出',
				children: (
					<div
						ref={containerRef2}
						className={`relative w-full pt-4 ${isFullScreen && 'fixed inset-0 z-50'} ${
							isDarkMode ? 'bg-[#1e1e1e]' : 'bg-white'
						} `}
					>
						<Flex justify="flex-end">
							<FullScreenButton containerRef={containerRef2} isFullScreen={isFullScreen} setIsFullScreen={setIsFullScreen} />
						</Flex>
						<CodeMirror
							className={`${isFullScreen ? 'h-[100%]' : 'h-[488px]'} overflow-auto`}
							value={logData.find(log => log.stepId === activeTab)?.logStdOut || ''}
							extensions={[StreamLanguage.define(shell), StreamLanguage.define(yaml), ...(isDarkMode ? createDarkTheme() : [])]}
							editable={false}
						/>
					</div>
				)
				// <CodeContainer ref={containerRef2} value={logData.find(log => log.stepId === activeTab)?.logStdOut || ''} />
			}
		],
		[activeTab, logData, isDarkMode, createDarkTheme, isFullScreen]
	);

	const getLog = async () => {
		let api: string;
		let params;

		if (type === 'jobProgress') {
			api = APIConfig.getLog;
			params = {
				ClusterId: id || selectCluster,
				JobId: jobId,
				NodeId: nodeId
			};
		} else if (type === 'nodeJobProgress') {
			api = APIConfig.getNodeLog;
			params = {
				ClusterId: id || selectCluster,
				NodeJobId: jobNodeId,
				NodeId: nodeId
			};
		} else {
			throw new Error(`Unknown type: ${type}`);
		}

		const data = await RequestHttp.get(api, { params });
		const {
			Data: { NodeJobLogList, JobLogList }
		} = data;

		// 根据不同类型处理数据
		const processedData = (type === 'jobProgress' ? JobLogList : NodeJobLogList).map((item: JobLogVo | NodeJobLogVo) =>
			unifyLogData(item, type)
		);

		setLogData(processedData);
	};

	useEffect(() => {
		(selectCluster || id) && getLog();
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [selectCluster, id]);

	useEffect(() => {
		if (!logData.length) return;

		const tabs: TabsProps['items'] = logData.map(item => ({
			key: item.stepId,
			label: (
				<Flex justify="space-between">
					<Popover placement="right" title={renderPopoverContent(item)} color="white" overlayInnerStyle={{ color: 'black' }}>
						<span className="inline-block w-[250px] truncate text-left">{item.stepName.split(':').pop()}</span>
					</Popover>
				</Flex>
			)
		}));

		setTabsData(tabs);
		setActiveTab(tabs[tabs.length - 1].key); // 默认选中最后一项，通常错误日志出现在最后一项
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [logData]);

	const renderPopoverContent = (log: UnifiedLogData) => {
		if (type === 'jobProgress') {
			// 处理 job 类型数据
			return (
				<div className="ml-2">
					<h3> {log.stepName.split(':').pop()}</h3>
					<p>阶段名称: {log.stageName}</p>
					<p>阶段 ID: {log.stageId}</p>
					<p>任务名称: {log.taskName}</p>
					<p>任务 ID: {log.taskId}</p>
					<p>步骤名称: {log.stepName}</p>
					<p>步骤 ID: {log.stepId}</p>
				</div>
			);
		} else if (type === 'nodeJobProgress') {
			// 处理 node 类型数据
			return (
				<div className="ml-2">
					<h3> {log.stepName.split(':').pop()}</h3>
					<p>任务名称: {log.taskName}</p>
					<p>任务 ID: {log.taskId}</p>
					<p>步骤名称: {log.stepName}</p>
					<p>步骤 ID: {log.stepId}</p>
				</div>
			);
		}
	};

	return (
		<Modal
			title={t('node.log')}
			width="90%"
			open={isModalOpen}
			onCancel={handleCancel}
			footer={[
				<Button key="cancel" onClick={handleCancel}>
					{t('close')}
				</Button>
			]}
			className="min-w-[1000px]"
		>
			<Flex>
				<Row className="w-[100%] h-[100%] min-w-[1px]">
					<Col span={6}>
						<Card className="no-padding-left">
							{tabsData?.length ? (
								<Tabs
									className="h-[590px]"
									tabBarStyle={{ width: '100%' }}
									tabPosition="left"
									items={tabsData}
									activeKey={activeTab}
									onChange={activeKey => {
										setActiveTab(activeKey);
									}}
								/>
							) : (
								<div className="h-[590px] flex aligh-center justify-center">暂无日志</div>
							)}
						</Card>
					</Col>
					<Col span={18}>
						<Card>
							<Tabs items={tabItems} tabBarExtraContent={<ThemeToggle onChange={setIsDarkMode} />} />
						</Card>
					</Col>
				</Row>
			</Flex>
		</Modal>
	);
});

export default CheckLogModal;
